第16天,今天聽到一句同事說的話:如果你不知道你做的選擇正不正確,那就把你做的選擇變成正確的吧。
大概是我認識他以來講過最帥的一句話
在程式開發中,許多時候並不希望某個類別一開始就非常龐大,一次就包含許多職責。那麼我們就可以使用裝飾者模式。裝飾者模式可以動態給某物件添加一些額外的職責,而不會影響這個類別派生的其他物件。
這次直接用裝飾者模式舉個例子。我們現在要做個飛機射擊遊戲,一開始只能發送普通飛彈,晉級的時候可以發射導彈,再升等可以發射原子彈,以傳統物件導向來做的話可以這麼做:
先做個基本飛機物件,只能發射普通子彈
var Plane = function () { };
Plane.prototype.fire = function () {
console.log('發射普通子彈');
};
再來做個發射導彈物件,它就是一個只能發射導彈的物件,那要從誰發射呢?當然是要帶入飛機囉
var MissileDecorator = function (plane) {
this.plane = plane;
};
MissileDecorator.prototype.fire = function () {
this.plane.fire();
console.log('發射導彈');
};
原子彈也是一樣道理
var AtomDecorator = function (plane) {
this.plane = plane;
};
AtomDecorator.prototype.fire = function () {
this.plane.fire();
console.log('發射原子彈');
};
這時候大致完成了,現在需要實際產出一台飛機,並且把導彈與原子彈安裝上去
var plane = new Plane();
plane = new MissileDecorator(plane);
plane = new AtomDecorator(plane);
實際發射就會接續發射普通子彈、導彈與原子彈了
plane.fire();
這種物件動態增加職責的方式,並沒有真正改動到Plane物件本身,而是將它放入到另一個物件之中。因為裝飾者(AtomDecorator與MissileDecorator)與他裝飾的物件(Plane)有一致的介面,所以對使用這個物件的使用者來說是透明的,被裝飾的物件也不需要了解自己曾經被裝飾過,這樣做法可以讓我們任意套用多個裝飾物件。
而JavaScript語言其實本身動態改變物件相當容易,我們可以直接改寫物件,來換個做法改寫一下:
一樣把所有物件先做好,不一樣的是將原形類別內容改為物件
var plane = {
fire: function () {
console.log('發射普通子彈');
}
};
var missileDecorator = function () {
console.log('發射導彈');
};
var atomDecorator = function () {
console.log('發射原子彈');
};
這時候先產生一個fire1物件內容就是原本的fire內容
var fire1 = plane.fire;
然後再將原本fire的內容覆蓋為執行fire1與導彈的內容
plane.fire = function () {
fire1();
missileDecorator();
};
之後原子彈的做法也是一樣
var fire2 = plane.fire;
plane.fire = function () {
fire2();
atomDecorator();
};
plane.fire();
今天先簡單講解裝飾者模式,明天會更細部說明